<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>



<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<LINK rel="stylesheet" type="text/css" href="embroot.css">
<TITLE>
Passing generic C or C++ data to ECLiPSe
</TITLE>
</HEAD>
<BODY >
<A HREF="embroot010.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="embroot007.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<HR>

<H2 CLASS="section"><A NAME="htoc26">3.4</A>&nbsp;&nbsp;Passing generic C or C++ data to ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP></H2><UL>
<LI><A HREF="embroot011.html#toc17">Wrapping and unwrapping external data in an ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> term</A>
<LI><A HREF="embroot011.html#toc18">The method table</A>
</UL>


<A NAME="@default60"></A>
It is possible to include any C or C++ data in an ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> term. To do this
it is wrapped into a handle to tell ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> that this is external data.
You also have to supply a method table, which is a set of functions
that are called when ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> wants to make common operations that it
assumes can be done on any data (eg. comparing, printing).<BR>
<BR>
<A NAME="toc17"></A>
<H3 CLASS="subsection"><A NAME="htoc27">3.4.1</A>&nbsp;&nbsp;Wrapping and unwrapping external data in an ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> term</H3>
To create an ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> wrapper for a C/C++ object,
the function <CODE>handle()</CODE> is used. It takes a pointer to any C or C++
data, and a pointer to a suitable method table (<CODE>t_ext_type</CODE> structure)
and creates an ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> handle term which refers to them.
Method tables for the common case of arrays of char, long or double
<A NAME="@default61"></A>
are predefined. For example a handle for a double array is made like this
<PRE CLASS="verbatim">
    double my_array[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
    EC_word w = handle(&amp;ec_xt_double_arr, my_array);
</PRE>where <CODE>ec_xt_double_arr</CODE> is a predefined method table for arrays of doubles.
To convert back from an ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> term <CODE>is_handle()</CODE> is used.
The method table passed in indicates the sort of data you expect to get.
If the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> handle contains the wrong sort, the function returns
TYPE_ERROR:
<PRE CLASS="verbatim">
    if ((EC_succeed == w.is_handle(&amp;ec_xt_double_arr, &amp;obj))
        obj-&gt;my_method();
    else
        cerr &lt;&lt; "unexpected type\n";
</PRE>
<A NAME="toc18"></A>
<H3 CLASS="subsection"><A NAME="htoc28">3.4.2</A>&nbsp;&nbsp;The method table</H3>
<A NAME="@default62"></A>
Apart from the predefined method tables ec_xt_double_arr,
ec_xt_long_arr and ec_xt_char_arr, new ones can easily be defined.
The address of the table is used as a type identifier, so when you
get an external object back from ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> you can check its type
to determine the kinds of operations you can do on it.
You can choose not to implement one or more of these functions, by
leaving a null pointer (<CODE>(void*)0</CODE>) in its field.
<PRE CLASS="verbatim">
    typedef void *t_ext_ptr;

    typedef struct {
        void       (*free)       (t_ext_ptr obj);
        t_ext_ptr  (*copy)       (t_ext_ptr obj);
        void       (*mark_dids)  (t_ext_ptr obj);
        int        (*string_size)(t_ext_ptr obj, int quoted);
        int        (*to_string)  (t_ext_ptr obj, char *buf, int quoted);
        int        (*equal)      (t_ext_ptr obj1, t_ext_ptr obj2);
        t_ext_ptr  (*remote_copy)(t_ext_ptr obj);
        EC_word    (*get)        (t_ext_ptr obj, int idx);
        int        (*set)        (t_ext_ptr obj, int idx, EC_word data);
    } t_ext_type;
</PRE>
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<B>void free(t_ext_ptr obj)</B><DD CLASS="dd-description">
<A NAME="@default63"></A>
This is called by ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> if it loses a reference to the external
data. This could happen if the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> execution were to fail
to a point before the external object was created, or if a
permanent copy was explicitly removed with built-ins like
<A HREF="../bips/kernel/storage/setval-2.html"><B>setval/2</B></A><A NAME="@default64"></A>,
<A HREF="../bips/kernel/record/erase-2.html"><B>erase/2</B></A><A NAME="@default65"></A>
or <A HREF="../bips/kernel/storage/bag_dissolve-2.html"><B>bag_dissolve/2</B></A><A NAME="@default66"></A>.
Note that an invocation of this function only means that <EM>one</EM>
reference has been deleted (while the copy function indicates that
a reference is added).<BR>
<BR>
<DT CLASS="dt-description"><B>t_ext_ptr copy(t_ext_ptr obj)</B><DD CLASS="dd-description">
This is called by ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> when it wants to make a copy of an object.
This happens when calling ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> built-ins like <A HREF="../bips/kernel/storage/setval-2.html"><B>setval/2</B></A><A NAME="@default67"></A> or
<A HREF="../bips/kernel/record/recordz-2.html"><B>recordz/2</B></A><A NAME="@default68"></A> which make permanent copies of data. The return value is
the copy.
If no copy-method is specified, these operations will not be possible
with terms that contain an object of this type.
A possible implementation is to return a pointer to the original and
e.g. increment a reference counter (and decrement the counter in
the free-method correspondingly).<BR>
<BR>
<DT CLASS="dt-description"><B>void mark_dids( t_ext_ptr obj)</B><DD CLASS="dd-description">
This is called during dictionary garbage collection. If an external
object contains references to the dictionary (<CODE>dident</CODE>) then
it needs to mark these as referenced.<BR>
<BR>
<DT CLASS="dt-description"><B>int string_size(t_ext_ptr obj, int quoted)</B><DD CLASS="dd-description">
<DT CLASS="dt-description"><B>int to_string(t_ext_ptr obj,char *buf, int quoted)</B><DD CLASS="dd-description">
When ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> wants to print an external object it calls <CODE>string_size()</CODE>
to get an estimate of how large the string would be that represents it.
This is used by ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> to allocate a buffer. The string representation must
be guaranteed to fit in the buffer.<BR>
<BR>
Finally the <CODE>to_string()</CODE> function is called. This should write the
string representation of the object into the buffer, and return the actual
size of that string.<BR>
<BR>
<DT CLASS="dt-description"><B>int equal(t_ext_ptr obj1, t_ext_ptr obj2)</B><DD CLASS="dd-description">
This is called when two external objects are unified or compared.
Prolog views the external object as a ground, atomic element.
It should return non-zero if the objects are considered equal.<BR>
<BR>
<DT CLASS="dt-description"><B>t_ext_ptr remote_copy(t_ext_ptr obj)</B><DD CLASS="dd-description">
This is called by parallel ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> when it needs to make a copy of an
object in another worker. If the object is in shared memory, this method
can be the same as the copy method.<BR>
<BR>
<DT CLASS="dt-description"><B>EC_Word get(t_ext_ptr obj, int idx)</B><DD CLASS="dd-description">
Returns the value of a field of the C++ object.
This methods gets invoked when the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicate <A HREF="../bips/kernel/externals/xget-3.html"><B>xget/3</B></A><A NAME="@default69"></A> is called.
The mapping of index values to fields is defined by the get/set-method pair.<BR>
<BR>
<DT CLASS="dt-description"><B>int set(t_ext_ptr obj, int idx, EC_word data)</B><DD CLASS="dd-description">
Set the value of a field of the C++ object.
This methods gets invoked when the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicate <A HREF="../bips/kernel/externals/xset-3.html"><B>xset/3</B></A><A NAME="@default70"></A> is called.
The mapping of index values to fields is defined by the get/set-method pair.
</DL>
Example of the simplest possible user-defined method table:
<PRE CLASS="verbatim">
    t_ext_type my_type = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
    my_struct data_in;
    ...
    // creating a handle for data_in
    EC_word w = handle(&amp;my_type, &amp;data_in);
    ...
    // checking a handle and extracting the data pointer
    my_struct *data_out;
    if ((EC_succeed == w.is_handle(&amp;my_type, &amp;data_out))
        data_out-&gt;my_method();
    else
        cerr &lt;&lt; "unexpected type\n";
</PRE>
<HR>
<A HREF="embroot010.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="embroot007.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
</BODY>
</HTML>
